package com.example.demo.scheduledtask;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.example.demo.mapper.PoMpsinfoMapper;
import com.example.demo.vo.*;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;

import javax.xml.soap.*;
import javax.xml.transform.Source;
import javax.xml.transform.Transformer;
import javax.xml.transform.TransformerFactory;
import javax.xml.transform.stream.StreamResult;
import javax.xml.transform.stream.StreamSource;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Field;
import java.net.URL;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 *
 */
@Component
@Slf4j
@DS("mes")
public class ApPoMorderBackfillScheduledTask {
    @Autowired
    PoMpsinfoMapper poMpsinfoMapper;

    /**
     * 生产工单回填（回填标识为‘是’，已经存在派工单并且对接单据号为空的生产工单），每分钟执行一次
     */
    @Scheduled(cron = "0 0/1 * * * ?")
    @Async(value = "taskExecutor")
    public void poMorderBackfillScheduledTask() {
        List<PoMorderVo> poMorderVoList = poMpsinfoMapper.getPoMorderVoList();
        if(poMorderVoList == null || poMorderVoList.size() == 0){
            return;
        }

        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");

        if(poMorderVoList != null && poMorderVoList.size() > 0){
            for(PoMorderVo poMorderVo : poMorderVoList){
                poMorderVo.setSfaadocno("5112");
                poMorderVo.setSfaasite("AMA");
                poMorderVo.setSfaadocdt(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
                poMorderVo.setSfaa003(String.valueOf(1));
                poMorderVo.setSfaa004(String.valueOf(1));
                poMorderVo.setSfaa005(String.valueOf(9));
                poMorderVo.setSfaa062("Y");
                poMorderVo.setSfaaua001("APS反填");
                poMorderVo.setSfaa068("4032");

                //获取工单配料
                List<PoMorderMaterialVo> poMorderMaterialVoList = poMpsinfoMapper.getPoMorderMaterialVoList(poMorderVo.getSfaa006());

                //发送SOAP回填
                startPoMorderBackFill(poMorderVo,poMorderMaterialVoList);
            }
        }
    }

    private void startPoMorderBackFill(PoMorderVo poMorderVo,List<PoMorderMaterialVo> poMorderMaterialVoList) {
        //获取xml格式参数
        String resMessage = getSoapXml(poMorderVo, poMorderMaterialVoList);

        try {
            //转换为soap消息
            MessageFactory msgFactory = MessageFactory.newInstance();
            SOAPMessage message = msgFactory.createMessage();
            SOAPPart soapPart = message.getSOAPPart();
            byte[] buffer = resMessage.getBytes();
            ByteArrayInputStream stream = new ByteArrayInputStream(buffer);
            StreamSource source = new StreamSource(stream);
            soapPart.setContent(source);
            message.writeTo(System.out);

            //发送soap消息，并解析结果
            String result = sendSoapMessage(message);
            if(result.contains("单据生成成功！")){
                //获取生成的ERP单号
                String billNo = result.substring(result.indexOf("AMA"),result.indexOf("AMA")+18);

                //更新生产工单对接单号
                poMpsinfoMapper.updatePoMorderErpFillBackPoMorder(billNo, poMorderVo.getSfaa006());
            }
        }catch (Exception e){
            e.printStackTrace();
        }
    }

    private String sendSoapMessage(SOAPMessage message) {
        String xmlData = "";
        try {
            // 创建连接
            SOAPConnectionFactory soapConnFactory = SOAPConnectionFactory.newInstance();
            SOAPConnection soapConn = soapConnFactory.createConnection();

            URL url = new URL("http://172.19.255.3/wtoptst/ws/r/awsp900");
            // 响应消息
            SOAPMessage reply = soapConn.call(message, url);
            // 创建soap消息转换对象
            TransformerFactory transformerFactory = TransformerFactory.newInstance();
            Transformer transformer = transformerFactory.newTransformer();
            // 提取消息内容
            Source sourceContent = reply.getSOAPPart().getContent();
            //输出流
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            StreamResult result = new StreamResult(out);
            //sourceContent实现此接口的对象包含充当源输入（XML 源或转换指令）所需的信息
            //result充当转换结果的持有者，可以为 XML、纯文本、HTML 或某些其他格式的标记
            transformer.transform(sourceContent, result);
            //返回结果
            xmlData = new String(out.toByteArray());
            //关闭连接
            soapConn.close();
        }catch (Exception e){
            e.printStackTrace();
        }

        return xmlData;
    }

    public <T,K> String getSoapXml(T obj, List<K> objs){
        //正理生能项目回填ERP协议框架
        String start = "<soapenv:Envelope xmlns:soapenv=\"http://schemas.xmlsoap.org/soap/envelope/\" xmlns:tip=\"http://www.digiwin.com.cn/tiptop/TIPTOPServiceGateWay\">\n" +
                "   <soapenv:Header/>\n" +
                "   <soapenv:Body>\n" +
                "      <tip:invokeSrv>\n" +
                "         <request>&lt;?xml version=\"1.0\" encoding=\"UTF-8\"?&gt;\n" +
                "&lt;request type=\"sync\" key=\"d41d8cd98f00b204e9800998ecf8427e\"&gt;\n" +
                "    &lt;host prod=\"AMA\" ver=\"1.0\" ip=\"10.0.0.1\" id=\"\" lang=\"zh_CN\" timezone=\"+8\" timestamp=\"1658122245035\" acct=\"tiptop\"/&gt;\n" +
                "    &lt;service prod=\"T100\" name=\"CreateProductOrder\" srvver=\"1.0\" ip=\"172.19.255.3\" id=\"toptst\"/&gt;\n" +
                "    &lt;datakey type=\"FOM\"&gt;\n" +
                "        &lt;key name=\"EntId\"&gt;5&lt;/key&gt;\n" +
                "        &lt;key name=\"CompanyId\"&gt;AMA&lt;/key&gt;\n" +
                "    &lt;/datakey&gt;\n" +
                "    &lt;payload&gt;\n" +
                "        &lt;param key=\"data\" type=\"XML\"&gt;\n" +
                "            &lt;![CDATA[\n" +
                "            &lt;Request&gt;\n" +
                "             &lt;RequestContent&gt;\n" +
                "              &lt;Document&gt;\n" +
                "               &lt;RecordSet id='1'&gt;\n" +
                "                &lt;Master name='sfaa_t' node_id='1'&gt;";
        String end = "&lt;/Master&gt;\n" +
                "               &lt;/RecordSet&gt;\n" +
                "             &lt;/Document&gt;\n" +
                "           &lt;/RequestContent&gt;\n" +
                "          &lt;/Request&gt;\n" +
                "         ]]&gt;\n" +
                "        &lt;/param&gt;\n" +
                "    &lt;/payload&gt;\n" +
                "&lt;/request&gt;\n" +
                "</request>\n" +
                "      </tip:invokeSrv>\n" +
                "   </soapenv:Body>\n" +
                "</soapenv:Envelope>";

        //组装主表xml
        String mainTableXml = getXmlFromObject(obj);
        mainTableXml = "\n&lt;Record&gt;\n" + "&lt;Field name='ActionType' value='I'/&gt;\n" +
                mainTableXml + "&lt;/Record&gt;";

        //组装物料附表xml
        String detailTableXml = "";
        if (objs != null && objs.size() > 0){
            for(K objDetail : objs){
                String temp = getXmlFromObject(objDetail);
                detailTableXml = detailTableXml + "&lt;Record&gt;\n" + temp + "&lt;/Record&gt;\n";
            }

            detailTableXml = "&lt;Detail name='sfba_t' node_id='1_1'&gt;\n" + detailTableXml + "&lt;/Detail&gt;\n";
        }

        return start+mainTableXml+detailTableXml+end;
    }

    private String getXmlFromObject(Object obj) {
        String result = "";

        Field[] fields = obj.getClass().getDeclaredFields();

        for (Field item : fields) {
            try {
                item.setAccessible(true);

                result = result + "&lt;Field name=" + "'" + item.getName()+ "'" + " value=" + "'" + item.get(obj)  + "'" + "/&gt;\n";
            }catch (Exception e){
                e.printStackTrace();
            }
        }

        result = result.replaceAll("null","");
        return result;
    }
}
